var baseAjax = {
    defaultLocation: null,
    enableHistory: true,
    enableEventListener: false,
    debugCallBack: false,

    init: function() {

        // init loading
        this.initLoading();

        // init history manager if enable
        if (this.enableHistory) {
            this.initHistory();
        }

        // ajaxify Links and Form
        this.ajaxify(document);
    },

    initHistory: function() {

        // history support
        dhtmlHistory.initialize();
        dhtmlHistory.addListener(this.historyChange.bind(this));

        // determine what our initial location is
        // by retrieving it from the browser's
        // location after the hash
        currentLocation = dhtmlHistory.getCurrentLocation();
        if (currentLocation == '') {
            var url = String(document.location);
            this.defaultLocation = this.getHashFromUrl(url);
            historyStorage.put(this.defaultLocation, url + '::');
        }
    },

    initLoading: function()
    {
        Ajax.clicked_obj = null;
        Ajax.loading_cnt = 0;
        Ajax.loading_div = $('loading');
        Event.observe(document, 'scroll', this.scrollLoading.bindAsEventListener(this));

        Ajax.Responders.register({
            onLoading: function() {
                Ajax.loading_cnt++;
                Ajax.loading_div.show();
            }
        });
    },

    ajaxify: function(root)
    {
        // if no root arg set root as document
        if (typeof(root) == 'undefined') {
            var root = document;
        }

        root = $(root);

        // parse links
        current = root.getElementsByTagName('a');
        curLen = current.length;
        for (j = 0; j < curLen; j++) {
            if (current[j].name != 'ajax') {
                continue;
            }
            this.ajaxifyLink(current[j]);
        }

        // parse forms
        current = root.getElementsByTagName('input');
        curLen = current.length;
        for (j = 0; j < curLen; j++) {
            if (current[j].name != 'ajax' || !current[j].form) {
                continue;
            }
            this.addAjaxForm(current[j].form);
        }

        if (Ajax.loading_cnt == 0) {
            Ajax.loading_div.hide();
        }
    },

    addAjaxForm: function(form)
    {
        form = $(form);
        if (typeof(form.alreadyObserved) == 'undefined') {
            form.alreadyObserved = true;
            form.submitForm = this.submitForm.bind(this, form);
            form.observe('submit', this.checkFormSubmit.bindAsEventListener(this, form));
            if (!form.getInputs('submit').length) {
                inputs = form.getInputs();
                for (i = 0; i < inputs.length; i++) {
                    if (inputs[i].type != 'password' && inputs[i].type != 'text') {
                        continue;
                    }

                    inputs[i].observe('keyup', this.checkFormSubmit.bindAsEventListener(this, form));
                }
            }
        }
    },

    ajaxifyLink: function(node)
    {
        node = $(node);
        if (typeof(node.alreadyObserved) == 'undefined') {
            node.alreadyObserved = true;

            if (!baseAjax.enableEventListener)
            {
                node.onclick = baseAjax.clickWithOnClick
            } else {
                node.listner = this.clickWithEventListener.bindAsEventListener(this, node);
                node.observe('click', node.listner);
            }
        }
    },

    clickWithOnClick: function()
    {
        Ajax.clicked_obj = this;
        baseAjax.request(Ajax.clicked_obj.href, false);
        return false;
    },

    clickWithEventListener: function(e, node)
    {
        Ajax.clicked_obj = $(node);
        this.request(Ajax.clicked_obj.href, baseAjax.hasHistory(Ajax.clicked_obj));
        Event.stop(e);
    },

    deAjaxifyLink: function(node)
    {
        link.stopObserving('click', link.listner);
    },

    scrollLoading: function(event)
    {
        res = document.documentElement.scrollTop || document.body.scrollTop;
        Ajax.loading_div.setStyle({top: res + 'px'});
    },

    saveClientBodyHeight: function()
    {
        var body = document.getElementsByTagName('body');
        body[0].oldHeight = body[0].style.height;
        body[0].style.height = body[0].clientHeight + 'px';
    },

    resetClientBodyHeight: function()
    {
        var body = document.getElementsByTagName('body');
        body[0].style.height = body[0].oldHeight;
    },

    ajaxCallback: function(XHR, eJSON)
    {
        try {

            // Get body.clientHeight and set has body.style.heigth
            // to fix scrolltop on dom resize.
            baseAjax.saveClientBodyHeight();

            eval(eJSON);

            // Reset body.style.heigth
            baseAjax.resetClientBodyHeight();

        } catch (e) {
            if (baseAjax.debugCallBack)
            {
                alert(e.message);
            }
        }

        if (Ajax.clicked_obj && Ajax.clicked_obj.submited) {
            Ajax.clicked_obj.submited = false;
        }
        if (Ajax.loading_cnt > 0) {
            Ajax.loading_cnt--;
        }
        if (Ajax.loading_cnt == 0) {
            Ajax.loading_div.hide();
        }
    },

    hasHistory: function(e) {

        if (baseAjax.enableHistory && e.hasClassName('no_history')) {
            return true;
        }

        return false;
    },

    request: function(url, noHistory)
    {
        var pars = '';

        if (!noHistory) {
            dhtmlHistory.add(this.getHashFromUrl(url), url + '::' + pars);
        }

        var baseAjax = new Ajax.Request(url,
            {
                method: 'get',
                parameters: pars,
                onComplete: this.ajaxCallback.bind(this)
            });
    },

    submitForm: function(form)
    {
        form = $(form);
        form.submited = true;
        Ajax.clicked_obj = form;
        form.request({
            onComplete: this.ajaxCallback.bind(this)
        });
    },

    checkFormSubmit: function(e, form)
    {
        Event.stop(e);
        form = $(form);

        if ((!e.keyCode || e.keyCode == Event.KEY_RETURN) && !form.submited) {
            this.submitForm(form);
        }
    },

    historyChange: function(newLocation, historyData)
    {
        this.displayLocation(historyData);
    },

    displayLocation: function(historyData)
    {
        if (!historyData) {
            if (!this.defaultLocation) {
                var hash = String(document.location).split('#')[1];
                if (!hash || !hash.length) {
                    return ;
                }
                historyData = historyStorage.get(hash);
            } else {
                historyData = historyStorage.get(this.defaultLocation);
            }
        }

        if (historyData) {
            var a = historyData.split('::');
            var myAjax = new Ajax.Request(a[0],
                {
                    method: 'get',
                    parameters: a[1],
                    onComplete: this.ajaxCallback.bind(this)
                }
          );
        }
    },

    getHashFromUrl: function(url)
    {
        return (MD5Hash.hex_md5(url));
    }
}
